//import minimist from 'minimist'
var minimist = require("minimist");
var cluster = require('cluster');

var fs = require("fs");
//var URL = require("url");
var microtime = require("microtime");

var packageJson = require("./package.json");
var io = require("socket.io-client")
let processCount = 8;
const argv = minimist(process.argv.slice(2), { '--': true });
let suppressError = false;
let startMoment_accept = microtime.now();
let loss_count = 0;//掉线次数




const showVersion = argv.v || argv.version
if (showVersion) {
    showToolVersion()
    return
}

suppressError = argv.suppressError

const concurrency = argv.c || 1
const requests = (argv.n || 1) * (argv.c || 1)
const urls = argv._
if (!urls) {
    throw new Error('Expect url')
}
if (urls.length !== 1) {
    throw new Error('Expect only one url')
}
const url = urls[0]

const startUser = (argv.u || 13800138000)
const filepath = argv.f
const file = filepath ? fs.readFileSync(filepath).toString() : ''
const contentType = argv.T || 'text/plain'
let startMoment = microtime.now();
let requestDate = {
    login: {//登录
        times: [],//耗时
        total: 0,//请求总次数
        success: 0,//成功次数
        fail: 0,//失败次数
        error: 0
    },
    acceptOrder: {//抢单
        times: [],//耗时
        total: 0,//请求总次数
        success: 0,//成功次数
        fail: 0,//失败次数
        error: 0
    },
}
function showResult() {
    const time = microtime.now() - startMoment;
    console.log(`并发用户量:      ${argv.c * argv.n}`)
    console.log(`断线用户数:      ${loss_count}`)
    console.log(`-------------------------------------------------------------`)
    // console.log(JSON.stringify(requestDate));
    for (let index in requestDate) {
        console.log('请求的方法:' + index);
        console.log(`完成请求数:      ${requestDate[index].success}`)
        console.log(`错误请求数:        ${requestDate[index].fail}`)
        console.log(`请求服务器异常数:        ${requestDate[index].error}`)

        console.log(`请求平均时间:           ${(requestDate[index].times.reduce((p, c) => p + c, 0) / requests / 1000000.0).toFixed(3)} [s]`)
        requestDate[index].times.sort((a, b) => a - b)
        console.log(`请求最大时间:               ${(requestDate[index].times[0] / 1000000.0).toFixed(3)} [s]`)
        console.log(`请求最小时间:               ${(requestDate[index].times[requestDate[index].times.length - 1] / 1000000.0).toFixed(3)} [s]`)
        console.log(`-------------------------------------------------------------`)

    }





    // tslint:enable:no-console
}

function showToolVersion() {
    console.log(`Version: ${packageJson.version}`)
}


// tslint:disable-next-line:cognitive-complexity
async function executeCommandLine() {



    if (url.startsWith('http://') || url.startsWith('https://')) {

        for (let i = 0; i < concurrency; i++) {
            (function (i) {
                const socket = io(url);
                let logintime = microtime.now();

                // console.log('begin');
                // console.log(microtime.now());
                socket.on('connect', function () {
                    console.log('connect!');
                    let message = {
                        name: 'login',
                        total: 1

                    }
                    process.send(message);
                    socket.emit('login', { username: 'abc', password: '123123', phone: 13000000000 + i + Math.floor(Math.random() * 100), type: 1 });
                });


                socket.on('res', function (data) {
                    // console.log('res:' + JSON.stringify(data));
                    let time = new Date();


                    if (data.code == 0 && data.msgname == 'login') {
                        // console.log('login');
                        requestDate['login'].times.push(microtime.now() - logintime);
                        let message = {
                            name: 'login',
                            times: microtime.now() - logintime,
                            success: 0,
                            fail: 0,
                            error: 0
                        }
                        if (data.code == 0) {
                            message.success = 1;
                        } else if (data.code == -999) {
                            message.error = 1;
                        }
                        else {
                            message.fail = 1;
                        }
                        process.send(message);

                        // process.send({ cmd: 'notifyRequest' });
                        // socket.emit('acceptOrder', { acceptOrder: '20190617192813246' });
                    } else if (data.msgname == 'sendOrder') {


                        time = microtime.now();
                        socket.emit('acceptOrder', { acceptOrder: data.data.ordernum });
                    } else if (data.msgname == 'acceptOrder') {



                        let message = {
                            name: 'acceptOrder',
                            times: microtime.now() - time,
                            success: 0,
                            fail: 0,
                            error: 0
                        };

                        if (data.code == 0) {
                            message.success = 1;
                        } else if (data.code == -999) {
                            message.error = 1;
                        }
                        else {
                            message.fail = 1;
                        }
                        process.send(message);
                    }

                });
                socket.on('disconnect', function () {
                    // console.log('disconnect');
                    let message = {
                        name: 'loss_count',
                    }
                    process.send(message);
                });
            })(i);
        }
    } else {
        throw new Error('Invalid url')
    }
}


if (cluster.isMaster) {
    if (!processCount) {
        processCount = require('os').cpus().length;
    }
    for (var i = 0; i < argv.n; i++) {
        cluster.fork();
    }

    cluster.on('fork', function (worker) {
        console.log("[fork]", worker.id);


        console.log("worker start");
    });
    setInterval(function () {
        showResult()
    }, 1000);

    cluster.on('exit', function (worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
    cluster.on('listening', function (worker, address) {
        console.log("A worker with #" + worker.id + " is now connected to " +
            address.address + ":" + address.port);
    });



    for (const id in cluster.workers) {
        cluster.workers[id].on('message', (msg) => {
            // console.log(JSON.stringify(msg));
            if (msg.name == 'loss_count') {
                loss_count++;
            }
            else {
                if (msg.times)
                    requestDate[msg.name].times.push(msg.times);
                if (msg.success)
                    requestDate[msg.name].success += msg.success;
                if (msg.fail)
                    requestDate[msg.name].fail += msg.fail;
                if (msg.total)
                    requestDate[msg.name].total += msg.total;
                if (msg.error)
                    requestDate[msg.name].error += msg.error;
            }

        });
    }

} else {

    executeCommandLine().then(() => {
        console.log('ws-benchmark success.');

    }, error => {
        if (error instanceof Error) {
            console.log(error.message)
        } else {
            console.log(error)
        }
        if (!suppressError) {
            process.exit(1)
        }
    })
}



